<template>

  <div>
    <Layout>
      <Content class="layout-content">

        <Row>
          <Col span="24">
            <Tabs v-model="funcValue" @on-click="tabClick">
              <TabPane label="json输入" name="jsonInput">


                <Split v-model="split" style="height: 366px">
                  <template #left>
                    <div v-show="split>0">
                      <Row>
                        <Col span="4">
                          请求地址：
                        </Col>
                        <Col span="16">
                          <Input v-model="requestUrl" placeholder="请输入请求地址"/>
                        </Col>
                        <Col span="0.5">
                          &nbsp;
                        </Col>
                        <Col span="2">
                          <Button type="primary" @click="sendRequest">请求</Button>
                        </Col>
                      </Row>

                      <Row>
                        <Col span="24">
                          <Tag color="primary">入参</Tag>
                        </Col>
                      </Row>
                      <Row>
                        <Col span="24">
                          <Codemirror
                              class="code"
                              v-model="inParam"
                              :style="{ height: '308px' }"
                              :extensions="extensions"
                              :autofocus="true"
                              :disabled="false"
                              @ready="handleClick('ready', $event)"
                              @change="handleClick('change', $event)"
                              @focus="handleClick('focus', $event)"
                              @blur="handleClick('blur', $event)"
                          >
                          </Codemirror>
                        </Col>
                      </Row>
                    </div>
                  </template>
                  <template #right>
                    <div style="margin-left: 6px">
                      <Row>
                        <Col span="22">
                          <Tag color="success">{{ inputCategoryCode }}</Tag>
                        </Col>
                        <Col span="2">
                          <Select v-model="inputCategoryCode" class="m-2" placeholder="Select" size="large"
                          >
                            <Option
                                v-for="item in inputOptions"
                                :key="item.value"
                                :label="item.label"
                                :value="item.value"
                            ></Option>
                          </Select>
                        </Col>
                      </Row>
                      <Row>
                        <Col span="24">
                          <Codemirror
                              class="code"
                              v-model="outJson"
                              :style="{ height: '340px' }"
                              :extensions="extensions"
                              :autofocus="true"
                              :disabled="false"
                              @ready="handleClick('ready', $event)"
                              @change="handleClick('change', $event)"
                              @focus="handleClick('focus', $event)"
                              @blur="handleClick('blur', $event)"
                          >
                          </Codemirror>
                        </Col>
                      </Row>

                      <Row>
                        <Col span="24">
                          &nbsp;
                        </Col>
                      </Row>
                      <Row>
                        <Col span="20">
                          &nbsp;
                        </Col>
                        <Col span="2">
                          <Button type="primary" @click="jsonPathResolve">jsonPath</Button>

                          <Modal
                              v-model="jsonPathModel"
                              title="请输入jsonPath"
                              @on-ok="jsonPathOk"
                              @on-cancel="jsonPathModel =false;">
                            <Input v-model="jsonPathKey" placeholder="请输入jsonPath"/>
                          </Modal>

                        </Col>
                      </Row>
                    </div>
                  </template>
                </Split>

              </TabPane>
              <TabPane label="字段映射" name="fieldMapping">
                <Row>
                  <Col span="20">

                  </Col>
                  <Col span="3">
                    <Select v-model="mappingKey" allow-create filterable @on-change="mappingChange"
                            @on-create="createMapping">
                      <Option v-for="item in mappingList" :value="item.value" :key="item.value">{{
                          item.label
                        }}
                      </Option>
                    </Select>
                  </Col>
                </Row>
                <Row>
                  <Col span="24">
                    <Codemirror
                        class="code"
                        v-model="mappingJson"
                        :style="{ height: '410px' }"
                        :extensions="extensions"
                        :autofocus="true"
                        :disabled="false"
                        @ready="handleClick('ready', $event)"
                        @change="handleClick('change', $event)"
                        @focus="handleClick('focus', $event)"
                        @blur="handleClick('blur', $event)"
                    >
                    </Codemirror>
                  </Col>
                </Row>
                <Row>
                  <Col span="24">
                    &nbsp;
                  </Col>
                </Row>
                <Row>
                  <Col span="22">
                    &nbsp;
                  </Col>

                  <Col span="2">
                    <Button type="primary" @click="saveMapping">保存</Button>
                  </Col>
                </Row>

              </TabPane>
              <TabPane label="表格结果" name="tableResult">

                <Row>
                  <Col span="20">

                  </Col>
                  <Col span="3">
                    <Select v-model="mappingKey" filterable @on-change="mappingChange">
                      <Option v-for="item in mappingList" :value="item.value" :key="item.value">{{
                          item.label
                        }}
                      </Option>
                    </Select>
                  </Col>
                </Row>
                <Row>
                  <Col span="24">
                    <div id="table-cont" v-html="tableHtml" style="height: 410px;width: 100%;overflow: scroll;">
                    </div>
                  </Col>
                </Row>

                <Row>
                  <Col span="22">
                    &nbsp;
                  </Col>
                  <Col span="2">
                    <Button type="primary" @click="downloadExcel">下载excel</Button>
                  </Col>
                </Row>

              </TabPane>
            </Tabs>

          </Col>
        </Row>
      </Content>
    </Layout>
  </div>
</template>
<script setup>
import {onMounted, ref, toRaw, inject, getCurrentInstance, compile, resolveComponent} from "vue";
import {Codemirror} from "vue-codemirror";
import {javascript} from "@codemirror/lang-javascript";
import {oneDark} from "@codemirror/theme-one-dark";
import {Message, Sider} from "view-ui-plus";
import api from "../request/apis.js";
import jsonpath from "jsonpath";

import {
  generateTable,
  generateHTMLTable,
  generateExcel,
  parseDataToSchema
} from 'json5-to-table'
import {getValue, setValue} from "../utils/index.js";
import X2JS from "x2js";

const inputCategoryCode = ref("json");

const inputOptions = ref([
  {
    value: 'json',
    label: 'json'
  },
  {
    value: 'xml',
    label: 'xml'
  }
])
const split = ref(0)

const mappingKey = ref(``);

const funcValue = ref(`jsonInput`);
const mappingList = ref([])
// const tableData = ref([]);

const jsonPathKey = ref(`$.records`);

const tableHtml = ref();

const mappingJson = ref();

const inParam = ref(`{
  "serviceFirstCategory": "FH0101.05",
  "current": 1,
  "size": 1000,
  "deptId": "146",
  "startDate": "2023-12-10",
  "endDate": "2023-12-10"
}`);

// const columns = ref([]);

const outJson = ref(``);

const requestUrl = ref(`/hbos-appointment/outpatient/appointment/pageAppointment`);
const extensions = [javascript(), oneDark];

const jsonPathModel = ref(false);

const sendRequest = async () => {
  let data = inParam.value;
  if (data) {
    data = JSON.parse(data);
  }
  const res = await api.send(requestUrl.value, data);
  outJson.value = JSON.stringify(res, null, 2);
}
const handleClick = (type, val) => {
  // console.log(type, val);
};
const jsonPathResolve = () => {
  jsonPathModel.value = true;
}
const jsonPathOk = () => {
  if (!jsonPathKey.value) {
    return;
  }
  let data = outJson.value;

  if (!data) {
    return;
  }

  data = JSON.parse(data);
  data = jsonpath?.query(data, jsonPathKey.value);
  if (data) {
    data = data[0];
    outJson.value = JSON.stringify(data, null, 2);
  }
}

const tabClick = () => {

  if (funcValue.value == 'tableResult' && outJson.value) {


    setTimeout(function () {
      jsonToTable();
    }, 0);


  }
}

const createMapping = (d) => {
  let filterFlag = false;
  for (let never of mappingList.value) {
    if (never.value == d) {
      filterFlag = true;
    }
  }
  if (filterFlag) {
    return
  }
  mappingList.value.push({
    value: d,
    label: d
  })
}
const jsonToTable = () => {

  const {data, columns} = getSchemaAndData();
  const th = generateHTMLTable(data, columns);

  tableHtml.value = th;
  scrollTable();
}

const getSchemaAndData = () => {
  let s = null;
  if (inputCategoryCode.value == 'xml') {
    var x2js = new X2JS();
    s = x2js.xml2js(outJson.value);
  } else {
    s = JSON.parse(outJson.value);
  }

  let b = parseDataToSchema(s);
  b = transforJsonSchema(b);
  return {
    data: s,
    columns: b
  }
}

const scrollTable = () => {
  var tableCont = document.querySelector('#table-cont');

  function scrollHandle(event) {
    var scrollTop = event.target.scrollTop;
    event.target.querySelector('thead').style.transform = 'translateY(' + (scrollTop - 1) + 'px)';
  }

  tableCont.addEventListener('scroll', scrollHandle);
}

const transforJsonSchema = (b) => {
  let value = mappingJson.value;
  if (!value || !value.trim()) {
    return b;
  }
  if (!b) {
    return b;
  }
  value = JSON.parse(value);
  repeatSetValue(b, value);
  return b;
}
const repeatSetValue = (b, value) => {
  for (const bi in b) {
    var bs = b[bi];
    var title = bs.title;
    var bsb = findHasKey(title, value);
    if (bsb) {
      bs.title = `${bsb}(${title})`;
    }
    var props = bs.props;

    if (props && props.length > 0) {
      repeatSetValue(props, value);
    }
  }
}


const findHasKey = (key, data) => {
  for (const bi in data) {
    if (key == bi) {
      return data[bi];
    }
  }
}

const downloadExcel = () => {
  const {data, columns} = getSchemaAndData();
  generateExcel(data, columns, {writeTo: 'export.xlsx'});
}

const saveMapping = () => {
  if (!mappingKey.value) {
    Message.info("请选设置映射环境");
    return;
  }
  for (let never of mappingList.value) {
    if (never.value == mappingKey.value) {
      never.mappingContent = mappingJson.value;
    }
  }
  setValue({
    mappingList: toRaw(mappingList.value),
    mappingKey: toRaw(mappingKey.value)
  });
  Message.info("保存成功");
}

const mappingChange = (d) => {
  for (let never of mappingList.value) {
    if (never.value == d) {
      mappingJson.value = never.mappingContent || '';
    }
  }
  tabClick();
}

onMounted(() => {
  getValue(function (value) {
    if (value) {
      mappingList.value = value.mappingList || [];
      mappingKey.value = value.mappingKey || '';
      mappingChange(mappingKey.value);
    }
  });
})

</script>
<style scoped>
.layout-content {
  background-color: white;
}
</style>